package com.zpb.framework.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zpb.framework.domain.ApiResult;
import com.zpb.framework.domain.dto.*;
import com.zpb.framework.domain.entity.Role;
import com.zpb.framework.domain.entity.User;
import com.zpb.framework.domain.entity.UserRole;
import com.zpb.framework.domain.enums.ResultCodeEnum;
import com.zpb.framework.domain.vo.*;
import com.zpb.framework.mapper.RoleMapper;
import com.zpb.framework.mapper.UserMapper;
import com.zpb.framework.mapper.UserRoleMapper;
import com.zpb.framework.service.UserService;
import com.zpb.framework.utils.BeanCopyUtil;
import com.zpb.framework.utils.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @Description:
 * @Author: zhaopengbo
 * @Date: 2025/9/10
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RoleMapper roleMapper;

    public ApiResult userChecker(UserCheckDto userCheckDto) {
        Long count = 0L;
        LambdaQueryWrapper<User> queryWrapper = null;
        queryWrapper = new LambdaQueryWrapper<User>().eq(User::getUsername, userCheckDto.getUsername());
        count = userMapper.selectCount(queryWrapper);
        if (count > 0) {
            return ApiResult.failure(ResultCodeEnum.EXIST_USERNAME);
        }
        queryWrapper = new LambdaQueryWrapper<User>().eq(User::getEmail, userCheckDto.getEmail());
        count = userMapper.selectCount(queryWrapper);
        if (count > 0) {
            return ApiResult.failure(ResultCodeEnum.EXIST_EMAIL);
        }
        queryWrapper = new LambdaQueryWrapper<User>().eq(User::getNickName, userCheckDto.getNickName());
        count = userMapper.selectCount(queryWrapper);
        if (count > 0) {
            return ApiResult.failure(ResultCodeEnum.EXIST_NICKNAME);
        }
        queryWrapper = new LambdaQueryWrapper<User>().eq(User::getPhoneNumber, userCheckDto.getPhoneNumber());
        count = userMapper.selectCount(queryWrapper);
        if (count > 0) {
            return ApiResult.failure(ResultCodeEnum.EXIST_PHONE);
        }
        return ApiResult.success();
    }

    @Override
    public ApiResult<UserVo> queryCurrentUserInfo() {
        User user = userMapper.selectById(SecurityUtils.getCurrentId());
        if (user == null) {
            return ApiResult.failure(ResultCodeEnum.NO_USER);
        }
        return ApiResult.success(BeanCopyUtil.copyBean(user, UserVo.class));
    }

    @Override
    public ApiResult updateUserInfo(UserDto userDto) {
        int result = userMapper.updateById(BeanCopyUtil.copyBean(userDto, User.class));
        if(result > 0){
            return ApiResult.success();
        }
        return ApiResult.failure(ResultCodeEnum.UPDATE_FAILURE);
    }

    @Override
    public ApiResult register(RegisterDto registerDto) {

        UserCheckDto userCheckDto = BeanCopyUtil.copyBean(registerDto, UserCheckDto.class);
        ApiResult apiResult = userChecker(userCheckDto);
        if (apiResult.getCode()!=ResultCodeEnum.SUCCESS.getCode()) {
            return apiResult;
        }

        registerDto.setPassword(passwordEncoder.encode(registerDto.getPassword()));
        User user = BeanCopyUtil.copyBean(registerDto, User.class);
        user.setSex("0");

        int result = userMapper.insert(user);
        if(result > 0){
            return ApiResult.success(null,"用户注册成功");
        }
        return ApiResult.failure(ResultCodeEnum.ADD_FAILURE.getCode(),"用户注册失败");
    }

    @Override
    public ApiResult<PageVo> getUserList(Integer pageNum, Integer pageSize, UserQueryDto userQueryDto) {
        Page userPage = new Page(pageNum, pageSize);
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>();
        queryWrapper.like(userQueryDto.getUsername()!=null,User::getUsername,userQueryDto.getUsername())
                .like(userQueryDto.getPhoneNumber()!=null,User::getPhoneNumber,userQueryDto.getPhoneNumber())
                .eq(userQueryDto.getStatus()!=null,User::getStatus,userQueryDto.getStatus())
                .orderByDesc(User::getCreateTime);
        page(userPage,queryWrapper);

        PageVo pageVo = new PageVo(userPage.getTotal(),userPage.getRecords());
        return ApiResult.success(pageVo);

    }

    @Override
    @Transactional
    public ApiResult addUser(UserAddDto userAddDto) {
        UserCheckDto userCheckDto = BeanCopyUtil.copyBean(userAddDto, UserCheckDto.class);
        ApiResult apiResult = userChecker(userCheckDto);
        if (apiResult.getCode()!=ResultCodeEnum.SUCCESS.getCode()) {
            return apiResult;
        }
        if(userAddDto.getSex() == null || Objects.isNull(userAddDto)){
            userAddDto.setSex("0");
        }

        userAddDto.setPassword(passwordEncoder.encode(userAddDto.getPassword()));
        User user = BeanCopyUtil.copyBean(userAddDto, User.class);
        int result = userMapper.insert(user);
        if(result == 0){
            return ApiResult.failure(ResultCodeEnum.ADD_FAILURE);
        }
        Long userId = user.getId();
        List<Long> roleIds = userAddDto.getRoleIds();

        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId,userId);
        Long count = userRoleMapper.selectCount(wrapper);
        if (count > 0) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ApiResult.error(ResultCodeEnum.UNKNOWN_ERROR);
        }
        for (Long roleId : roleIds) {
            int addRoleResultFlag = userRoleMapper.insert(new UserRole(userId, roleId));
            if (addRoleResultFlag == 0) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ApiResult.error(ResultCodeEnum.ADD_FAILURE);
            }
        }
        return ApiResult.success();
    }

    @Override
    public ApiResult delUser(Long id) {
        int result = userMapper.deleteById(id);
        if(result > 0){
            return ApiResult.success();
        }
        return ApiResult.failure(ResultCodeEnum.DEL_FAILURE);
    }

    @Override
    public ApiResult<UserWithRoleVo> getUserWithRoleById(Long id){
        //获取用户
        User user = userMapper.selectById(id);
        if(Objects.isNull(user)){
            return ApiResult.failure(ResultCodeEnum.NO_USER);
        }
        UserEchoVo userEchoVo = BeanCopyUtil.copyBean(user, UserEchoVo.class);
        // 获取roleId列表
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId,user.getId());
        List<UserRole> userRoles = userRoleMapper.selectList(wrapper);
        List<Long> roleIds = new ArrayList<>();
        if(userRoles.size() > 0){
            roleIds = userRoles.stream().map(UserRole::getRoleId).toList();
        }

        // 获取全部role
        List<Role> roles = roleMapper.selectList(null);
        List<RoleVo> roleVos = BeanCopyUtil.copyBeanList(roles, RoleVo.class);

        // 封装
        UserWithRoleVo userWithRoleVo = new UserWithRoleVo(roleIds,roleVos,userEchoVo);
        return ApiResult.success(userWithRoleVo);


    }

    @Override
    @Transactional
    public ApiResult updateUserById(UserUpdateDto userUpdateDto) {
        User user = BeanCopyUtil.copyBean(userUpdateDto, User.class);
        int result = userMapper.updateById(user);
        if(result == 0){
            return ApiResult.failure(ResultCodeEnum.UPDATE_FAILURE);
        }
        LambdaQueryWrapper<UserRole> userRoleWrapper = new LambdaQueryWrapper<>();
        userRoleWrapper.eq(UserRole::getUserId,user.getId());
        userRoleMapper.delete(userRoleWrapper);

        List<Long> roleIds = userUpdateDto.getRoleIds();
        for (Long roleId : roleIds) {
            int insertUserRoleResult = userRoleMapper.insert(new UserRole(user.getId(), roleId));
            if(insertUserRoleResult == 0){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ApiResult.error(ResultCodeEnum.UPDATE_FAILURE);
            }
        }
        return ApiResult.success();
    }
}
